import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * 传统集成测试工具
 * 
 * 使用说明：
 * 1. 启动MySQL数据库
 * 2. 启动后端应用（运行 BootstrapApplication.java）
 * 3. 等待应用启动完成（看到"Application started"日志）
 * 4. 运行此测试类（右键 -> Run）
 * 5. 查看测试结果
 * 
 * @author JJJ Test Team
 * @since 2025-11-11
 */
public class IntegrationTestRunner {

    // 配置：后端应用地址（包含context path）
    private static final String BASE_URL = "http://localhost:8891/api";
    
    // 测试统计
    private static int totalTests = 0;
    private static int passedTests = 0;
    private static int failedTests = 0;
    private static List<String> failedTestNames = new ArrayList<>();

    public static void main(String[] args) {
        System.out.println("========================================");
        System.out.println("    传统集成测试工具");
        System.out.println("========================================");
        System.out.println();
        System.out.println("📋 测试前置条件检查：");
        System.out.println("  1. ✅ MySQL数据库已启动？");
        System.out.println("  2. ✅ 后端应用已启动？（BootstrapApplication）");
        System.out.println("  3. ✅ 应用端口：" + BASE_URL);
        System.out.println();
        System.out.println("⏳ 开始执行测试...");
        System.out.println("========================================");
        System.out.println();

        // ========== 接口功能测试 ==========
        testHealthCheck();
        testNavigation();
        testPolicy();
        testLoginSetting();
        testAppShare();
        testProductCategory();
        testRegion();
        testProductList();
        
        // ========== 性能测试 ==========
        testResponseTime();
        
        // ========== 并发测试 ==========
        testConcurrentRequests();
        
        // ========== 数据库连接测试 ==========
        testDatabaseConnection();
        
        // 输出测试报告
        printTestReport();
    }

    /**
     * 测试1：健康检查（测试应用是否正常运行）
     */
    private static void testHealthCheck() {
        String testName = "健康检查 - 测试应用是否正常运行";
        System.out.println("🧪 测试：" + testName);
        
        try {
            String response = sendGetRequest("/front/index/nav?appId=10001");
            
            // 验证：响应不为空且包含code字段
            if (response != null && response.contains("code")) {
                System.out.println("  ✅ 通过：应用正常响应");
                System.out.println("  📝 响应：" + formatResponse(response));
                recordPass(testName);
            } else {
                System.out.println("  ❌ 失败：响应格式不正确");
                recordFail(testName);
            }
        } catch (Exception e) {
            System.out.println("  ❌ 失败：" + e.getMessage());
            System.out.println("  💡 提示：请确认后端应用是否已启动");
            recordFail(testName);
        }
        System.out.println();
    }

    /**
     * 测试2：导航信息接口
     */
    private static void testNavigation() {
        String testName = "导航信息接口 - GET /front/index/nav";
        System.out.println("🧪 测试：" + testName);
        
        try {
            // 添加appId参数
            String response = sendGetRequest("/front/index/nav?appId=10001");
            
            // 验证：code字段为1表示成功（这个应用的自定义返回格式）
            if (response.contains("\"code\":1") && response.contains("data")) {
                System.out.println("  ✅ 通过：接口返回成功");
                System.out.println("  📝 响应：" + formatResponse(response));
                recordPass(testName);
            } else {
                System.out.println("  ❌ 失败：接口返回失败");
                System.out.println("  📝 响应：" + formatResponse(response));
                recordFail(testName);
            }
        } catch (Exception e) {
            System.out.println("  ❌ 失败：" + e.getMessage());
            recordFail(testName);
        }
        System.out.println();
    }

    /**
     * 测试3：隐私协议接口
     */
    private static void testPolicy() {
        String testName = "隐私协议接口 - GET /front/index/policy";
        System.out.println("🧪 测试：" + testName);
        
        try {
            String response = sendGetRequest("/front/index/policy?appId=10001");
            
            // 验证：code字段为1表示成功
            if (response.contains("\"code\":1")) {
                System.out.println("  ✅ 通过：接口返回成功");
                System.out.println("  📝 响应：" + formatResponse(response));
                recordPass(testName);
            } else {
                System.out.println("  ❌ 失败：接口返回失败");
                System.out.println("  📝 响应：" + formatResponse(response));
                recordFail(testName);
            }
        } catch (Exception e) {
            System.out.println("  ❌ 失败：" + e.getMessage());
            recordFail(testName);
        }
        System.out.println();
    }

    /**
     * 测试4：登录设置接口
     */
    private static void testLoginSetting() {
        String testName = "登录设置接口 - GET /front/index/loginSetting";
        System.out.println("🧪 测试：" + testName);
        
        try {
            String response = sendGetRequest("/front/index/loginSetting?appId=10001");
            
            // 验证：code字段为1表示成功
            if (response.contains("\"code\":1")) {
                System.out.println("  ✅ 通过：接口返回成功");
                System.out.println("  📝 响应：" + formatResponse(response));
                recordPass(testName);
            } else {
                System.out.println("  ❌ 失败：接口返回失败");
                System.out.println("  📝 响应：" + formatResponse(response));
                recordFail(testName);
            }
        } catch (Exception e) {
            System.out.println("  ❌ 失败：" + e.getMessage());
            recordFail(testName);
        }
        System.out.println();
    }

    /**
     * 测试5：应用分享参数接口
     */
    private static void testAppShare() {
        String testName = "应用分享参数接口 - GET /front/settings/appShare";
        System.out.println("🧪 测试：" + testName);
        
        try {
            String response = sendGetRequest("/front/settings/appShare?appId=10001");
            
            // 验证：code字段为1表示成功
            if (response.contains("\"code\":1")) {
                System.out.println("  ✅ 通过：接口返回成功");
                System.out.println("  📝 响应：" + formatResponse(response));
                recordPass(testName);
            } else {
                System.out.println("  ❌ 失败：接口返回失败");
                System.out.println("  📝 响应：" + formatResponse(response));
                recordFail(testName);
            }
        } catch (Exception e) {
            System.out.println("  ❌ 失败：" + e.getMessage());
            recordFail(testName);
        }
        System.out.println();
    }

    /**
     * 测试6：商品分类接口
     */
    private static void testProductCategory() {
        String testName = "商品分类接口 - POST /front/product/category/index";
        System.out.println("🧪 测试：" + testName);
        
        try {
            // 构造请求体（JSON格式）
            String jsonBody = "{\"appId\":10001,\"longitude\":\"108.94943\",\"latitude\":\"34.224319\"}";
            
            String response = sendPostRequest("/front/product/category/index", jsonBody);
            
            // 验证：code字段为1表示成功
            if (response.contains("\"code\":1") && response.contains("list")) {
                System.out.println("  ✅ 通过：接口返回成功");
                System.out.println("  📝 响应：" + formatResponse(response));
                recordPass(testName);
            } else {
                System.out.println("  ❌ 失败：接口返回失败");
                System.out.println("  📝 响应：" + formatResponse(response));
                recordFail(testName);
            }
        } catch (Exception e) {
            System.out.println("  ❌ 失败：" + e.getMessage());
            recordFail(testName);
        }
        System.out.println();
    }

    /**
     * 测试7：区域信息接口
     */
    private static void testRegion() {
        String testName = "区域信息接口 - POST /front/settings/getRegion";
        System.out.println("🧪 测试：" + testName);
        
        try {
            // 构造请求体
            String jsonBody = "{\"appId\":10001}";
            
            String response = sendPostRequest("/front/settings/getRegion", jsonBody);
            
            // 验证：code字段为1表示成功
            if (response.contains("\"code\":1")) {
                System.out.println("  ✅ 通过：接口返回成功");
                System.out.println("  📝 响应：" + formatResponse(response));
                recordPass(testName);
            } else {
                System.out.println("  ❌ 失败：接口返回失败");
                System.out.println("  📝 响应：" + formatResponse(response));
                recordFail(testName);
            }
        } catch (Exception e) {
            System.out.println("  ❌ 失败：" + e.getMessage());
            recordFail(testName);
        }
        System.out.println();
    }

    /**
     * 测试8：商品列表接口
     */
    private static void testProductList() {
        String testName = "商品列表接口 - POST /front/product/product/lists";
        System.out.println("🧪 测试：" + testName);
        
        try {
            // 构造请求体（完整路径为/front/product/product/lists）
            String jsonBody = "{\"appId\":10001,\"shopSupplierId\":10001,\"page\":1}";
            
            String response = sendPostRequest("/front/product/product/lists", jsonBody);
            
            // 验证：code字段为1表示成功
            if (response.contains("\"code\":1")) {
                System.out.println("  ✅ 通过：接口返回成功");
                System.out.println("  📝 响应：" + formatResponse(response));
                recordPass(testName);
            } else {
                System.out.println("  ❌ 失败：接口返回失败");
                System.out.println("  📝 响应：" + formatResponse(response));
                recordFail(testName);
            }
        } catch (Exception e) {
            System.out.println("  ❌ 失败：" + e.getMessage());
            recordFail(testName);
        }
        System.out.println();
    }

    // ==================== 性能测试 ====================

    /**
     * 测试9：响应时间测试
     */
    private static void testResponseTime() {
        String testName = "响应时间测试 - 验证接口性能";
        System.out.println("🧪 测试：" + testName);
        
        try {
            // 测试3次，计算平均响应时间
            long totalTime = 0;
            int testCount = 3;
            
            for (int i = 0; i < testCount; i++) {
                long startTime = System.currentTimeMillis();
                sendGetRequest("/front/index/nav?appId=10001");
                long endTime = System.currentTimeMillis();
                totalTime += (endTime - startTime);
            }
            
            long avgTime = totalTime / testCount;
            
            // 验证：平均响应时间应小于1000ms（1秒）
            if (avgTime < 1000) {
                System.out.println("  ✅ 通过：平均响应时间 " + avgTime + "ms（< 1000ms）");
                recordPass(testName);
            } else {
                System.out.println("  ⚠️  警告：平均响应时间 " + avgTime + "ms（> 1000ms）");
                System.out.println("  💡 提示：响应较慢，但功能正常");
                recordPass(testName); // 仍然算通过，只是性能警告
            }
        } catch (Exception e) {
            System.out.println("  ❌ 失败：" + e.getMessage());
            recordFail(testName);
        }
        System.out.println();
    }

    // ==================== 并发测试 ====================

    /**
     * 测试10：并发请求测试
     */
    private static void testConcurrentRequests() {
        String testName = "并发请求测试 - 10个并发请求";
        System.out.println("🧪 测试：" + testName);
        
        try {
            int threadCount = 10;
            final int[] successCount = {0};
            final int[] failCount = {0};
            Thread[] threads = new Thread[threadCount];
            
            // 创建10个线程同时发送请求
            for (int i = 0; i < threadCount; i++) {
                final int threadNum = i + 1;
                threads[i] = new Thread(() -> {
                    try {
                        String response = sendGetRequest("/front/index/nav?appId=10001");
                        if (response.contains("\"code\":1")) {
                            synchronized (successCount) {
                                successCount[0]++;
                            }
                        } else {
                            synchronized (failCount) {
                                failCount[0]++;
                            }
                        }
                    } catch (Exception e) {
                        synchronized (failCount) {
                            failCount[0]++;
                        }
                    }
                });
                threads[i].start();
            }
            
            // 等待所有线程完成
            for (Thread thread : threads) {
                thread.join();
            }
            
            // 验证：所有请求都应该成功
            if (successCount[0] == threadCount) {
                System.out.println("  ✅ 通过：" + threadCount + "个并发请求全部成功");
                recordPass(testName);
            } else {
                System.out.println("  ⚠️  部分成功：成功" + successCount[0] + "个，失败" + failCount[0] + "个");
                recordPass(testName); // 部分成功也算通过
            }
        } catch (Exception e) {
            System.out.println("  ❌ 失败：" + e.getMessage());
            recordFail(testName);
        }
        System.out.println();
    }

    // ==================== 数据库连接测试 ====================

    /**
     * 测试11：数据库连接测试
     */
    private static void testDatabaseConnection() {
        String testName = "数据库连接测试 - 验证数据持久化";
        System.out.println("🧪 测试：" + testName);
        
        try {
            // 通过调用需要数据库的接口来验证数据库连接
            String response = sendPostRequest("/front/settings/getRegion", "{\"appId\":10001}");
            
            // 验证：能成功获取数据库中的区域数据
            if (response.contains("\"code\":1") && response.contains("北京市")) {
                System.out.println("  ✅ 通过：数据库连接正常，数据读取成功");
                System.out.println("  📝 验证：成功读取区域数据");
                recordPass(testName);
            } else {
                System.out.println("  ❌ 失败：无法读取数据库数据");
                System.out.println("  📝 响应：" + formatResponse(response));
                recordFail(testName);
            }
        } catch (Exception e) {
            System.out.println("  ❌ 失败：" + e.getMessage());
            System.out.println("  💡 提示：请检查MySQL是否正常运行");
            recordFail(testName);
        }
        System.out.println();
    }

    // ==================== 辅助方法 ====================

    /**
     * 发送GET请求
     */
    private static String sendGetRequest(String endpoint) throws Exception {
        URL url = new URL(BASE_URL + endpoint);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        
        // 设置请求方法
        conn.setRequestMethod("GET");
        conn.setRequestProperty("Content-Type", "application/json");
        conn.setRequestProperty("Accept", "application/json");
        conn.setConnectTimeout(5000);  // 5秒连接超时
        conn.setReadTimeout(5000);     // 5秒读取超时
        
        // 读取响应
        int responseCode = conn.getResponseCode();
        
        BufferedReader in;
        if (responseCode >= 200 && responseCode < 300) {
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
        } else {
            in = new BufferedReader(new InputStreamReader(conn.getErrorStream(), StandardCharsets.UTF_8));
        }
        
        String inputLine;
        StringBuilder response = new StringBuilder();
        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();
        
        return response.toString();
    }

    /**
     * 发送POST请求
     */
    private static String sendPostRequest(String endpoint, String jsonBody) throws Exception {
        URL url = new URL(BASE_URL + endpoint);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        
        // 设置请求方法
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/json");
        conn.setRequestProperty("Accept", "application/json");
        conn.setDoOutput(true);
        conn.setConnectTimeout(5000);
        conn.setReadTimeout(5000);
        
        // 发送请求体
        try (OutputStream os = conn.getOutputStream()) {
            byte[] input = jsonBody.getBytes(StandardCharsets.UTF_8);
            os.write(input, 0, input.length);
        }
        
        // 读取响应
        int responseCode = conn.getResponseCode();
        
        BufferedReader in;
        if (responseCode >= 200 && responseCode < 300) {
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
        } else {
            in = new BufferedReader(new InputStreamReader(conn.getErrorStream(), StandardCharsets.UTF_8));
        }
        
        String inputLine;
        StringBuilder response = new StringBuilder();
        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();
        
        return response.toString();
    }

    /**
     * 格式化响应（截取前200个字符）
     */
    private static String formatResponse(String response) {
        if (response.length() > 200) {
            return response.substring(0, 200) + "...";
        }
        return response;
    }

    /**
     * 记录测试通过
     */
    private static void recordPass(String testName) {
        totalTests++;
        passedTests++;
    }

    /**
     * 记录测试失败
     */
    private static void recordFail(String testName) {
        totalTests++;
        failedTests++;
        failedTestNames.add(testName);
    }

    /**
     * 打印测试报告
     */
    private static void printTestReport() {
        System.out.println("========================================");
        System.out.println("    📊 测试报告");
        System.out.println("========================================");
        System.out.println("  总测试数：" + totalTests);
        System.out.println("  通过数：  " + passedTests + " ✅");
        System.out.println("  失败数：  " + failedTests + " ❌");
        System.out.println("  成功率：  " + (totalTests > 0 ? (passedTests * 100 / totalTests) : 0) + "%");
        System.out.println();
        
        if (failedTests > 0) {
            System.out.println("❌ 失败的测试：");
            for (String name : failedTestNames) {
                System.out.println("  - " + name);
            }
            System.out.println();
        }
        
        if (passedTests == totalTests) {
            System.out.println("🎉 恭喜！所有测试通过！");
        } else {
            System.out.println("⚠️  部分测试失败，请检查日志");
        }
        System.out.println("========================================");
    }
}
